package MusicLandscape.entities;

import MusicLandscape.Date;
import MusicLandscape.Venue;

/**
 * represents a generic event of an artist in a certain venue on certain date
 *
 * @author Jonas Altrock (ew20b126@technikum-wien.at)
 * @version 3
 * @since ExerciseSheet02
 */
public class Event {
    /**
     * the artist who appeared at this event the artist of an event cannot be null
     */
    private Artist artist = new Artist();

    /**
     * the number of attendees of this event.
     */
    private int attendees = 0;

    /**
     * the date on which this event takes place
     * <p>
     * a null date represents an unknown date
     */
    private Date date;

    /**
     * description of this event
     * <p>
     * default description is an empty String
     */
    private String description = "";

    /**
     * the venue at which this event takes place
     * <p>
     * a null venue represents an unknown venue
     */
    private Venue venue;

    /**
     * creates a default event
     * <p>
     * a default event has a default artist and an empty description. all other information is unknown (See docu for fields)
     */
    public Event() {
    }

    /**
     * creates a deep copy of an event
     *
     * @param e the event to copy
     */
    public Event(Event e) {
        artist = new Artist(e.artist);
        attendees = e.attendees;
        date = new Date(e.date);
        description = e.description;
        venue = new Venue(e.venue);
    }

    /**
     * gets the artist of this event
     *
     * @return the artist
     */
    public Artist getArtist() {
        return artist;
    }

    /**
     * sets the artist of this event
     * <p>
     * the artist of an event cannot be null
     *
     * @param artist the artist to set
     */
    public void setArtist(Artist artist) {
        if (artist == null) {
            return;
        }
        this.artist = artist;
    }


    /**
     * gets the number of attendees of this event
     *
     * @return the attendees
     */
    public int getAttendees() {
        return attendees;
    }

    /**
     * sets the number of attendees of this event
     * <p>
     * the number of attendees must be a non-negative number.
     * When called with invalid arguments this event remains unchanged.
     *
     * @param attendees the attendees to set
     */
    public void setAttendees(int attendees) {
        if (attendees < 0) {
            return;
        }
        this.attendees = attendees;
    }

    /**
     * gets the date of this event
     * <p>
     * this method is defensive in the sense that it returns a copy of the date
     *
     * @return the date
     */
    public Date getDate() {
        if (date == null) {
            return null;
        }
        return new Date(date);
    }

    /**
     * sets the date of this event
     * <p>
     * an unknown date is represented by a null date.
     * this method is defensive in the sense that this event keep a copy of the original date
     *
     * @param date the date to set
     */
    public void setDate(Date date) {
        if (date == null) {
            this.date = null;
            return;
        }
        this.date = new Date(date);
    }

    /**
     * gets the description of this event
     *
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * sets the description of this event
     * <p>
     * description can not be null
     *
     * @param description the description to set
     */
    public void setDescription(String description) {
        if (description == null) {
            return;
        }
        this.description = description;
    }

    /**
     * gets the venue of this event
     *
     * @return the Venue
     */
    public Venue getVenue() {
        return venue;
    }

    /**
     * sets the venue of this event
     *
     * @param venue the venue to set
     */
    public void setVenue(Venue venue) {
        this.venue = venue;
    }

    /**
     * returns a String representation of this event
     * <p>
     * the string representation of an event is (without quotes, but including line breaks):
     *
     * <pre>
     * "artist" @ "venue name" on "date"
     * "description"
     * ("attendees" attending ("impact"))
     * </pre>
     *
     * <p>
     * if a value is not available, replace it with "unknown"
     *
     * @return a String representation of this event
     */
    public String toString() {
        String artist = this.artist.getName();
        String venue = this.venue == null || this.venue.getName().isBlank() ?
                "unknown" : this.venue.getName();
        String date = this.date == null ? "null" : this.date.toString();

        return artist + " @ " + venue + " on " + date + "\n" +
                description + "\n" +
                "(" + attendees + " attending (" + impact() + "))";
    }

    /**
     * returns the impact of this event
     * <p>
     * the impact is an estimation of the number of people who took notice of this event
     * for a generic event, the impact is the number of attendees times 2.
     *
     * @return the impact
     */
    public int impact() {
        return attendees * 2;
    }
}
